// DecisionTreeRegistry.java
package org.zjx.core.controller;

import org.zjx.core.DecisionTree;
import org.zjx.exception.DecisionConfigurationException;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;

/**
 * 决策树注册中心（线程安全）
 * 这个类提供了线程安全的决策树注册和管理功能，允许多个决策树被注册和检索。
 */
public class DecisionTreeRegistry {
    // 使用ConcurrentHashMap保证线程安全
    private final ConcurrentMap<String, AtomicReference<DecisionTree>> registry = new ConcurrentHashMap<>();

    /**
     * 注册决策树
     * @param treeId 决策树ID
     * @param tree 决策树实例
     * @throws DecisionConfigurationException 如果决策树ID已存在
     */
    public void register(String treeId, DecisionTree tree) {
        registry.computeIfAbsent(treeId, k -> new AtomicReference<>()).set(tree);
    }

    /**
     * 获取决策树（可选）
     * @param treeId 决策树ID
     * @return 包含决策树的Optional，如果不存在则为空
     */
    public Optional<DecisionTree> get(String treeId) {
        return Optional.ofNullable(registry.get(treeId))
                .map(AtomicReference::get);
    }

    /**
     * 获取或创建决策树
     * @param treeId 决策树ID
     * @param supplier 决策树供应商（如果不存在则调用）
     * @return 决策树实例
     */
    public DecisionTree getOrCreate(String treeId, Supplier<DecisionTree> supplier) {
        registry.computeIfAbsent(treeId, k -> new AtomicReference<>()).set(supplier.get());
        return registry.get(treeId).get();
    }

    /**
     * 替换决策树
     * @param treeId 决策树ID
     * @param newTree 新的决策树实例
     * @return 被替换的决策树（如果存在）
     */
    public boolean  replace(String treeId, DecisionTree newTree) {
        AtomicReference<DecisionTree> ref = registry.get(treeId);
        if (ref == null) return false;

        DecisionTree oldTree = ref.get();
        ref.set(newTree);
        return true;
    }

    /**
     * 移除决策树
     * @param treeId 决策树ID
     * @param expectedTree 预期的决策树实例（用于验证）
     * @return 如果成功移除返回true
     */
    public boolean remove(String treeId, DecisionTree expectedTree) {
        return registry.remove(treeId).get() == expectedTree;
    }
}